#include "app_buffer.h"

// 初始化子缓冲区
static SubBuffer *app_buffer_init_subbuffer(int total_size)
{
    // 申请内存
    SubBuffer *sub_buffer = malloc(sizeof(SubBuffer));
    sub_buffer->ptr = malloc(total_size);
    sub_buffer->total_size = total_size;
    sub_buffer->len = 0;

    // 返回结果
    return sub_buffer;
}

// 切换读写缓冲区
static void app_buffer_swap_buffer(Buffer *buffer)
{
    log_info("准备切换缓冲区,并加锁...");
    pthread_mutex_lock(&buffer->write_lock);
    int temp = -1;
    temp = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = temp;
    log_info("切换缓冲区完成,并解锁...");
    pthread_mutex_unlock(&buffer->write_lock);
}

/**
 * 初始化缓冲区
 */
Buffer *app_buffer_init(int total_size)
{
    // 申请缓冲区内存
    Buffer *buffer = malloc(sizeof(Buffer));

    // 内部创建两个子缓冲区
    buffer->sub_buffer[0] = app_buffer_init_subbuffer(total_size);
    buffer->sub_buffer[1] = app_buffer_init_subbuffer(total_size);

    // 定义初始化读写缓冲区索引
    buffer->read_index = 0;
    buffer->write_index = 1;

    // 初始化两把锁
    pthread_mutex_init(&buffer->read_lock, NULL);
    pthread_mutex_init(&buffer->write_lock, NULL);

    // 返回缓冲区
    return buffer;
}

// 释放资源
void app_buffer_deinit(Buffer *buffer)
{
    // 1.释放子缓冲区中存放数据的内存
    free(buffer->sub_buffer[0]->ptr);
    free(buffer->sub_buffer[1]->ptr);

    // 2.释放子缓冲区结构体
    free(buffer->sub_buffer[0]);
    free(buffer->sub_buffer[1]);

    // 3.销毁锁
    pthread_mutex_destroy(&buffer->read_lock);
    pthread_mutex_destroy(&buffer->write_lock);

    // 4.释放大缓冲区
    free(buffer);
}

/**
 * 数据写入写缓冲区
 */
int app_buffer_write(Buffer *buffer, char *data, int data_len)
{
    // 判断当前写入数据的长度是否超过规定的单个消息大小
    if (data_len > MAX_MSG_SIZE)
    {
        log_error("当前写入数据的长度超过规定的单个消息大小...");
        return -1;
    }

    log_info("准备写数据,并加锁...");
    pthread_mutex_lock(&buffer->write_lock);

    // 取出写缓冲区
    SubBuffer *write_buffer = buffer->sub_buffer[buffer->write_index];

    // 计算缓冲区剩余空间并判断是否足够存储下当前数据
    if ((data_len + 1) > (write_buffer->total_size - write_buffer->len))
    {
        log_error("当前写缓冲区剩余空间不足并解锁...");
        pthread_mutex_unlock(&buffer->write_lock);
        return -1;
    }

    // 先写入当前数据的长度
    write_buffer->ptr[write_buffer->len] = data_len;

    // 再写入数据
    memcpy(write_buffer->ptr + write_buffer->len + 1, data, data_len);

    // 更新缓冲区中的数据长度
    write_buffer->len = write_buffer->len + data_len + 1;

    // 写数据完成并释放锁
    log_info("写数据完成并释放锁...");
    pthread_mutex_unlock(&buffer->write_lock);

    return 0;
}

/**
 * 读取缓冲区中的数据
 */
int app_buffer_read(Buffer *buffer, char *data_buf, int data_buf_len)
{
    // 准备读取数据并加锁
    log_info("准备读取数据并加锁...");
    pthread_mutex_lock(&buffer->read_lock);

    // 取出读缓冲区
    SubBuffer *read_buffer = buffer->sub_buffer[buffer->read_index];

    // 获取缓冲区中是否存在数据
    int read_buffer_len = read_buffer->len;
    if (read_buffer_len <= 0)
    {
        log_info("当前读缓冲区为空,准备切换读写缓冲区再次读取数据...");
        app_buffer_swap_buffer(buffer);

        read_buffer = buffer->sub_buffer[buffer->read_index];
        read_buffer_len = read_buffer->len;
        if (read_buffer_len <= 0)
        {
            log_info("整个缓冲区为空并解锁...");
            pthread_mutex_unlock(&buffer->read_lock);
            return -1;
        }
    }

    // 取出第一个字节,表示当前要读取数据的长度
    int data_len = read_buffer->ptr[0];

    // 判断当前待读取数据长度是否超过容器长度
    if (data_len > data_buf_len)
    {
        log_error("当前待读取数据长度超过容器长度并解锁...");
        pthread_mutex_unlock(&buffer->read_lock);
        return -1;
    }

    // 读取数据
    memcpy(data_buf, read_buffer->ptr + 1, data_len);

    // 将后续数据移动至缓冲区最前面
    int cur_len = read_buffer->len - data_len - 1;
    log_debug("读取之后读缓冲区中现有数据长度为：%d", cur_len);
    memmove(read_buffer->ptr, read_buffer->ptr + data_len + 1, cur_len);

    // 更新当前缓冲区中存储的数据长度
    read_buffer->len = cur_len;

    // 读取数据完成并释放锁
    log_info("读取数据完成并释放锁...");
    pthread_mutex_unlock(&buffer->read_lock);

    // 如果当前缓冲区空了,切换缓冲区,可以不做
    // if (cur_len <= 0)
    // {
    //     app_buffer_swap_buffer(buffer);
    // }

    return data_len;
}